🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / core / data / src / commonTest / kotlin / org / meshtastic / core / data / repository / CommonMeshLogRepositoryTest.kt
Displaying Raw • Download
core/data/src/commonTest/kotlin/org/meshtastic/core/data/repository/CommonMeshLogRepositoryTest.kt 492afbde5c98f3efdcd367ab2f13ef3665fe7388 (492afbde) Text, 12.53 KB
T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.core.data.repository
Tff7b72import T7ee787dev.mokkery.MockMode
Tff7b72import T7ee787dev.mokkery.answering.returns
Tff7b72import T7ee787dev.mokkery.every
Tff7b72import T7ee787dev.mokkery.mock
Tff7b72import T7ee787kotlinx.coroutines.flow.MutableStateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.first
Tff7b72import T7ee787kotlinx.coroutines.test.UnconfinedTestDispatcher
Tff7b72import T7ee787kotlinx.coroutines.test.runTest
Tff7b72import T7ee787okio.ByteString.Companion.toByteString
Tff7b72import T7ee787org.meshtastic.core.data.datasource.NodeInfoReadDataSource
Tff7b72import T7ee787org.meshtastic.core.database.entity.MyNodeEntity
Tff7b72import T7ee787org.meshtastic.core.di.CoroutineDispatchers
Tff7b72import T7ee787org.meshtastic.core.model.MeshLog
Tff7b72import T7ee787org.meshtastic.core.model.util.TELEMETRY_CHANNEL_COUNT
Tff7b72import T7ee787org.meshtastic.core.model.util.adcVoltage
Tff7b72import T7ee787org.meshtastic.core.model.util.oneWireTemperature
Tff7b72import T7ee787org.meshtastic.core.repository.MeshLogRetention
Tff7b72import T7ee787org.meshtastic.core.testing.FakeDatabaseProvider
Tff7b72import T7ee787org.meshtastic.core.testing.FakeMeshLogPrefs
Tff7b72import T7ee787org.meshtastic.proto.Data
Tff7b72import T7ee787org.meshtastic.proto.DeviceMetrics
Tff7b72import T7ee787org.meshtastic.proto.EnvironmentMetrics
Tff7b72import T7ee787org.meshtastic.proto.FromRadio
Tff7b72import T7ee787org.meshtastic.proto.LocalStats
Tff7b72import T7ee787org.meshtastic.proto.MeshPacket
Tff7b72import T7ee787org.meshtastic.proto.PortNum
Tff7b72import T7ee787org.meshtastic.proto.Telemetry
Tff7b72import T7ee787kotlin.test.AfterTest
Tff7b72import T7ee787kotlin.test.BeforeTest
Tff7b72import T7ee787kotlin.test.Test
Tff7b72import T7ee787kotlin.test.assertEquals
Tff7b72import T7ee787kotlin.test.assertNotNull
Tff7b72import T7ee787kotlin.test.assertTrue
Tff7b72import T7ee787kotlin.time.Duration.Companion.days
Tff7b72import T7ee787kotlin.time.Duration.Companion.hours
Tff7b72import T7ee787kotlin.time.Duration.Companion.minutes
Tff7b72import T7ee787org.meshtastic.core.common.util.nowMillis Tff7b72as Te6edf3realNowMillis
Tff7b72abstract Tff7b72class T56d364CommonMeshLogRepositoryTest Tb4b4b4{
Tff7b72protected Tff7b72lateinit Tff7b72var Te6edf3dbProviderTb4b4b4: Te6edf3FakeDatabaseProvider
Tff7b72protected Tff7b72lateinit Tff7b72var Te6edf3meshLogPrefsTb4b4b4: Te6edf3FakeMeshLogPrefs
Tff7b72protected Tff7b72lateinit Tff7b72var Te6edf3nodeInfoReadDataSourceTb4b4b4: Te6edf3NodeInfoReadDataSource
Tff7b72private Tff7b72val Te6edf3testDispatcher Tff7b72= Te6edf3UnconfinedTestDispatcherTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3dispatchers Tff7b72= Te6edf3CoroutineDispatchersTb4b4b4(Te6edf3main Tff7b72= Te6edf3testDispatcherTb4b4b4, Te6edf3io Tff7b72= Te6edf3testDispatcherTb4b4b4, Te6edf3default Tff7b72= Te6edf3testDispatcherTb4b4b4)
Tff7b72protected Tff7b72lateinit Tff7b72var Te6edf3repositoryTb4b4b4: Te6edf3MeshLogRepositoryImpl
Tff7b72private Tff7b72val Te6edf3nowMillis Tff7b72= T79c0ff1T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0L
Tf0883e@BeforeTest
Tff7b72fun Td2a8ffsetupRepoTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3dbProvider Tff7b72= Te6edf3FakeDatabaseProviderTb4b4b4(Tb4b4b4)
Te6edf3meshLogPrefs Tff7b72= Te6edf3FakeMeshLogPrefsTb4b4b4(Tb4b4b4)
Te6edf3meshLogPrefsTb4b4b4.Te6edf3setLoggingEnabledTb4b4b4(Tff7b72trueTb4b4b4)
Te6edf3nodeInfoReadDataSource Tff7b72= Te6edf3mockTb4b4b4(Te6edf3MockModeTb4b4b4.Te6edf3autofillTb4b4b4)
Te6edf3every Tb4b4b4{ Te6edf3nodeInfoReadDataSourceTb4b4b4.Te6edf3myNodeInfoFlowTb4b4b4(Tb4b4b4) Tb4b4b4} Te6edf3returns Te6edf3MutableStateFlowTb4b4b4(Tff7b72nullTb4b4b4)
Te6edf3repository Tff7b72= Te6edf3MeshLogRepositoryImplTb4b4b4(Te6edf3dbProviderTb4b4b4, Te6edf3dispatchersTb4b4b4, Te6edf3meshLogPrefsTb4b4b4, Te6edf3nodeInfoReadDataSourceTb4b4b4)
Tb4b4b4}
Tf0883e@AfterTest
Tff7b72fun Td2a8fftearDownTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3dbProviderTb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`parseTelemetryLog preserves zero temperature`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTestTb4b4b4(Te6edf3testDispatcherTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3zeroTemp Tff7b72= T79c0ff0.0f
Tff7b72val Te6edf3telemetry Tff7b72= Te6edf3TelemetryTb4b4b4(Te6edf3environment_metrics Tff7b72= Te6edf3EnvironmentMetricsTb4b4b4(Te6edf3temperature Tff7b72= Te6edf3zeroTempTb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3meshPacket Tff7b72=
Te6edf3MeshPacketTb4b4b4(Te6edf3decoded Tff7b72= Te6edf3DataTb4b4b4(Te6edf3payload Tff7b72= Te6edf3telemetryTb4b4b4.Te6edf3encodeTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toByteStringTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3portnum Tff7b72= Te6edf3PortNumTb4b4b4.Te6edf3TELEMETRY_APPTb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3meshLog Tff7b72=
Te6edf3MeshLogTb4b4b4(
Te6edf3uuid Tff7b72= Ta5d6ff"Ta5d6ff123Ta5d6ff"Tb4b4b4,
Te6edf3message_type Tff7b72= Ta5d6ff"Ta5d6fftelemetryTa5d6ff"Tb4b4b4,
Te6edf3received_date Tff7b72= Te6edf3nowMillisTb4b4b4,
Te6edf3raw_message Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4,
Te6edf3fromNum Tff7b72= T79c0ff0Tb4b4b4,
Te6edf3portNum Tff7b72= Te6edf3PortNumTb4b4b4.Te6edf3TELEMETRY_APPTb4b4b4.Te6edf3valueTb4b4b4,
Te6edf3fromRadio Tff7b72= Te6edf3FromRadioTb4b4b4(Te6edf3packet Tff7b72= Te6edf3meshPacketTb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3repositoryTb4b4b4.Te6edf3insertTb4b4b4(Te6edf3meshLogTb4b4b4)
Tff7b72val Te6edf3result Tff7b72= Te6edf3repositoryTb4b4b4.Te6edf3getTelemetryFromTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)
Te6edf3assertNotNullTb4b4b4(Te6edf3resultTb4b4b4)
Te6edf3assertEqualsTb4b4b4(T79c0ff1Tb4b4b4, Te6edf3resultTb4b4b4.Te6edf3sizeTb4b4b4)
Tff7b72val Te6edf3resultMetrics Tff7b72= Te6edf3resultTff7b72[T79c0ff0Tff7b72]Tb4b4b4.Te6edf3environment_metrics
Te6edf3assertNotNullTb4b4b4(Te6edf3resultMetricsTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3zeroTempTb4b4b4, Te6edf3resultMetricsTb4b4b4.Te6edf3temperature Tff7b72?: T79c0ff0fTb4b4b4, T79c0ff0.01fTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`deleteLogs redirects local node number to NODE_NUM_LOCAL`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTestTb4b4b4(Te6edf3testDispatcherTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3localNodeNum Tff7b72= T79c0ff9T79c0ff9T79c0ff9
Tff7b72val Te6edf3port Tff7b72= Te6edf3PortNumTb4b4b4.Te6edf3TEXT_MESSAGE_APPTb4b4b4.Te6edf3value
Tff7b72val Te6edf3myNodeEntity Tff7b72=
Te6edf3MyNodeEntityTb4b4b4(
Te6edf3myNodeNum Tff7b72= Te6edf3localNodeNumTb4b4b4,
Te6edf3model Tff7b72= Ta5d6ff"Ta5d6ffmodelTa5d6ff"Tb4b4b4,
Te6edf3firmwareVersion Tff7b72= Ta5d6ff"Ta5d6ff1.0Ta5d6ff"Tb4b4b4,
Te6edf3couldUpdate Tff7b72= Tff7b72falseTb4b4b4,
Te6edf3shouldUpdate Tff7b72= Tff7b72falseTb4b4b4,
Te6edf3currentPacketId Tff7b72= T79c0ff0LTb4b4b4,
Te6edf3messageTimeoutMsec Tff7b72= T79c0ff0Tb4b4b4,
Te6edf3minAppVersion Tff7b72= T79c0ff0Tb4b4b4,
Te6edf3maxChannels Tff7b72= T79c0ff0Tb4b4b4,
Te6edf3hasWifi Tff7b72= Tff7b72falseTb4b4b4,
Tb4b4b4)
Te6edf3every Tb4b4b4{ Te6edf3nodeInfoReadDataSourceTb4b4b4.Te6edf3myNodeInfoFlowTb4b4b4(Tb4b4b4) Tb4b4b4} Te6edf3returns Te6edf3MutableStateFlowTb4b4b4(Te6edf3myNodeEntityTb4b4b4)
Tff7b72val Te6edf3log Tff7b72=
Te6edf3MeshLogTb4b4b4(
Te6edf3uuid Tff7b72= Ta5d6ff"Ta5d6ff123Ta5d6ff"Tb4b4b4,
Te6edf3message_type Tff7b72= Ta5d6ff"Ta5d6ffTEXTTa5d6ff"Tb4b4b4,
Te6edf3received_date Tff7b72= Te6edf3nowMillisTb4b4b4,
Te6edf3raw_message Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4,
Te6edf3fromNum Tff7b72=
T79c0ff0Tb4b4b4, T8b949e// asEntity will map it if we pass localNodeNum to asEntity, but here we set it manually
Te6edf3portNum Tff7b72= Te6edf3portTb4b4b4,
Te6edf3fromRadio Tff7b72=
Te6edf3FromRadioTb4b4b4(
Te6edf3packet Tff7b72= Te6edf3MeshPacketTb4b4b4(Te6edf3from Tff7b72= Te6edf3localNodeNumTb4b4b4, Te6edf3decoded Tff7b72= Te6edf3DataTb4b4b4(Te6edf3portnum Tff7b72= Te6edf3PortNumTb4b4b4.Te6edf3TEXT_MESSAGE_APPTb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3repositoryTb4b4b4.Te6edf3insertTb4b4b4(Te6edf3logTb4b4b4)
T8b949e// Verify it's there
Te6edf3assertEqualsTb4b4b4(T79c0ff1Tb4b4b4, Te6edf3repositoryTb4b4b4.Te6edf3getAllLogsUnboundedTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3sizeTb4b4b4)
Te6edf3repositoryTb4b4b4.Te6edf3deleteLogsTb4b4b4(Te6edf3localNodeNumTb4b4b4, Te6edf3portTb4b4b4)
Tff7b72val Te6edf3logs Tff7b72= Te6edf3repositoryTb4b4b4.Te6edf3getAllLogsUnboundedTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3logsTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`deleteLocalStatsLogs deletes only local stats telemetry`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTestTb4b4b4(Te6edf3testDispatcherTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3nodeNum Tff7b72= T79c0ff1T79c0ff2T79c0ff3T79c0ff4
Tff7b72val Te6edf3localStatsLog Tff7b72=
Te6edf3telemetryLogTb4b4b4(
Te6edf3uuid Tff7b72= Ta5d6ff"Ta5d6fflocal-statsTa5d6ff"Tb4b4b4,
Te6edf3nodeNum Tff7b72= Te6edf3nodeNumTb4b4b4,
Te6edf3telemetry Tff7b72= Te6edf3TelemetryTb4b4b4(Te6edf3local_stats Tff7b72= Te6edf3LocalStatsTb4b4b4(Te6edf3noise_floor Tff7b72= Tff7b72-T79c0ff1T79c0ff1T79c0ff2Tb4b4b4)Tb4b4b4)Tb4b4b4,
Te6edf3receivedDate Tff7b72= Te6edf3nowMillis Tff7b72+ T79c0ff3Tb4b4b4,
Tb4b4b4)
Tff7b72val Te6edf3deviceLog Tff7b72=
Te6edf3telemetryLogTb4b4b4(
Te6edf3uuid Tff7b72= Ta5d6ff"Ta5d6ffdeviceTa5d6ff"Tb4b4b4,
Te6edf3nodeNum Tff7b72= Te6edf3nodeNumTb4b4b4,
Te6edf3telemetry Tff7b72= Te6edf3TelemetryTb4b4b4(Te6edf3device_metrics Tff7b72= Te6edf3DeviceMetricsTb4b4b4(Te6edf3battery_level Tff7b72= T79c0ff8T79c0ff0Tb4b4b4)Tb4b4b4)Tb4b4b4,
Te6edf3receivedDate Tff7b72= Te6edf3nowMillis Tff7b72+ T79c0ff2Tb4b4b4,
Tb4b4b4)
Tff7b72val Te6edf3environmentLog Tff7b72=
Te6edf3telemetryLogTb4b4b4(
Te6edf3uuid Tff7b72= Ta5d6ff"Ta5d6ffenvironmentTa5d6ff"Tb4b4b4,
Te6edf3nodeNum Tff7b72= Te6edf3nodeNumTb4b4b4,
Te6edf3telemetry Tff7b72= Te6edf3TelemetryTb4b4b4(Te6edf3environment_metrics Tff7b72= Te6edf3EnvironmentMetricsTb4b4b4(Te6edf3temperature Tff7b72= T79c0ff2T79c0ff1fTb4b4b4)Tb4b4b4)Tb4b4b4,
Te6edf3receivedDate Tff7b72= Te6edf3nowMillis Tff7b72+ T79c0ff1Tb4b4b4,
Tb4b4b4)
Tff7b72val Te6edf3localStatsRequestLog Tff7b72=
Te6edf3telemetryLogTb4b4b4(
Te6edf3uuid Tff7b72= Ta5d6ff"Ta5d6fflocal-stats-requestTa5d6ff"Tb4b4b4,
Te6edf3nodeNum Tff7b72= Te6edf3nodeNumTb4b4b4,
Te6edf3telemetry Tff7b72= Te6edf3TelemetryTb4b4b4(Te6edf3local_stats Tff7b72= Te6edf3LocalStatsTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4,
Te6edf3receivedDate Tff7b72= Te6edf3nowMillisTb4b4b4,
Te6edf3wantResponse Tff7b72= Tff7b72trueTb4b4b4,
Tb4b4b4)
Te6edf3listOfTb4b4b4(Te6edf3localStatsLogTb4b4b4, Te6edf3deviceLogTb4b4b4, Te6edf3environmentLogTb4b4b4, Te6edf3localStatsRequestLogTb4b4b4)Tb4b4b4.Te6edf3forEach Tb4b4b4{ Te6edf3repositoryTb4b4b4.Te6edf3insertTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}
Te6edf3repositoryTb4b4b4.Te6edf3deleteLocalStatsLogsTb4b4b4(Te6edf3nodeNumTb4b4b4)
Tff7b72val Te6edf3remainingIds Tff7b72= Te6edf3repositoryTb4b4b4.Te6edf3getAllLogsUnboundedTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3map Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3uuid Tb4b4b4}Tb4b4b4.Te6edf3toSetTb4b4b4(Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3setOfTb4b4b4(Ta5d6ff"Ta5d6ffdeviceTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffenvironmentTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fflocal-stats-requestTa5d6ff"Tb4b4b4)Tb4b4b4, Te6edf3remainingIdsTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`deleteLogsOlderThan one hour sentinel keeps the last hour instead of wiping the table`Tb4b4b4(Tb4b4b4) Tff7b72=
Te6edf3runTestTb4b4b4(Te6edf3testDispatcherTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3now Tff7b72= Te6edf3realNowMillis
Te6edf3repositoryTb4b4b4.Te6edf3insertTb4b4b4(Te6edf3retentionLogTb4b4b4(Ta5d6ff"Ta5d6ffrecentTa5d6ff"Tb4b4b4, Te6edf3now Tff7b72- T79c0ff3T79c0ff0.Te6edf3minutesTb4b4b4.Te6edf3inWholeMillisecondsTb4b4b4)Tb4b4b4)
Te6edf3repositoryTb4b4b4.Te6edf3insertTb4b4b4(Te6edf3retentionLogTb4b4b4(Ta5d6ff"Ta5d6ffstaleTa5d6ff"Tb4b4b4, Te6edf3now Tff7b72- T79c0ff2.Te6edf3hoursTb4b4b4.Te6edf3inWholeMillisecondsTb4b4b4)Tb4b4b4)
Te6edf3repositoryTb4b4b4.Te6edf3deleteLogsOlderThanTb4b4b4(Te6edf3MeshLogRetentionTb4b4b4.Te6edf3ONE_HOURTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3setOfTb4b4b4(Ta5d6ff"Ta5d6ffrecentTa5d6ff"Tb4b4b4)Tb4b4b4, Te6edf3repositoryTb4b4b4.Te6edf3getAllLogsUnboundedTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3map Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3uuid Tb4b4b4}Tb4b4b4.Te6edf3toSetTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`deleteLogsOlderThan keep forever sentinel deletes nothing`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTestTb4b4b4(Te6edf3testDispatcherTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3now Tff7b72= Te6edf3realNowMillis
Te6edf3repositoryTb4b4b4.Te6edf3insertTb4b4b4(Te6edf3retentionLogTb4b4b4(Ta5d6ff"Ta5d6ffancientTa5d6ff"Tb4b4b4, Te6edf3now Tff7b72- T79c0ff4T79c0ff0T79c0ff0.Te6edf3daysTb4b4b4.Te6edf3inWholeMillisecondsTb4b4b4)Tb4b4b4)
Te6edf3repositoryTb4b4b4.Te6edf3insertTb4b4b4(Te6edf3retentionLogTb4b4b4(Ta5d6ff"Ta5d6ffrecentTa5d6ff"Tb4b4b4, Te6edf3nowTb4b4b4)Tb4b4b4)
Te6edf3repositoryTb4b4b4.Te6edf3deleteLogsOlderThanTb4b4b4(Te6edf3MeshLogRetentionTb4b4b4.Te6edf3KEEP_FOREVERTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3setOfTb4b4b4(Ta5d6ff"Ta5d6ffancientTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffrecentTa5d6ff"Tb4b4b4)Tb4b4b4, Te6edf3repositoryTb4b4b4.Te6edf3getAllLogsUnboundedTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3map Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3uuid Tb4b4b4}Tb4b4b4.Te6edf3toSetTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`deleteLogsOlderThan trims to the configured day count`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTestTb4b4b4(Te6edf3testDispatcherTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3now Tff7b72= Te6edf3realNowMillis
Te6edf3repositoryTb4b4b4.Te6edf3insertTb4b4b4(Te6edf3retentionLogTb4b4b4(Ta5d6ff"Ta5d6ffwithinTa5d6ff"Tb4b4b4, Te6edf3now Tff7b72- T79c0ff6.Te6edf3daysTb4b4b4.Te6edf3inWholeMillisecondsTb4b4b4)Tb4b4b4)
Te6edf3repositoryTb4b4b4.Te6edf3insertTb4b4b4(Te6edf3retentionLogTb4b4b4(Ta5d6ff"Ta5d6ffoutsideTa5d6ff"Tb4b4b4, Te6edf3now Tff7b72- T79c0ff8.Te6edf3daysTb4b4b4.Te6edf3inWholeMillisecondsTb4b4b4)Tb4b4b4)
Te6edf3repositoryTb4b4b4.Te6edf3deleteLogsOlderThanTb4b4b4(T79c0ff7Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3setOfTb4b4b4(Ta5d6ff"Ta5d6ffwithinTa5d6ff"Tb4b4b4)Tb4b4b4, Te6edf3repositoryTb4b4b4.Te6edf3getAllLogsUnboundedTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3map Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3uuid Tb4b4b4}Tb4b4b4.Te6edf3toSetTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}
T8b949e/** Retention is measured against the real clock, so these rows are stamped relative to it. */
Tff7b72private Tff7b72fun Td2a8ffretentionLogTb4b4b4(Te6edf3uuidTb4b4b4: Tffa657StringTb4b4b4, Te6edf3receivedDateTb4b4b4: Tffa657LongTb4b4b4) Tff7b72=
Te6edf3MeshLogTb4b4b4(Te6edf3uuid Tff7b72= Te6edf3uuidTb4b4b4, Te6edf3message_type Tff7b72= Ta5d6ff"Ta5d6ffTEXTTa5d6ff"Tb4b4b4, Te6edf3received_date Tff7b72= Te6edf3receivedDateTb4b4b4, Te6edf3raw_message Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4)
Tf0883e@Test
Tff7b72fun Td2a8ff`parseTelemetryLog lifts legacy one-wire list onto per-channel fields`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTestTb4b4b4(Te6edf3testDispatcherTb4b4b4) Tb4b4b4{
T8b949e// Firmware before 2.8 emitted the repeated field; stored logs must still chart after the repoint.
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffDEPRECATIONTa5d6ff"Tb4b4b4)
Tff7b72val Te6edf3telemetry Tff7b72=
Te6edf3TelemetryTb4b4b4(Te6edf3environment_metrics Tff7b72= Te6edf3EnvironmentMetricsTb4b4b4(Te6edf3one_wire_temperature Tff7b72= Te6edf3listOfTb4b4b4(T79c0ff1T79c0ff1fTb4b4b4, T79c0ff0fTb4b4b4, T79c0ff3T79c0ff3fTb4b4b4)Tb4b4b4)Tb4b4b4)
Te6edf3repositoryTb4b4b4.Te6edf3insertTb4b4b4(Te6edf3telemetryLogTb4b4b4(Ta5d6ff"Ta5d6fflegacy-one-wireTa5d6ff"Tb4b4b4, T79c0ff0Tb4b4b4, Te6edf3telemetryTb4b4b4, Te6edf3nowMillisTb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3metrics Tff7b72= Te6edf3repositoryTb4b4b4.Te6edf3getTelemetryFromTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3singleTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3environment_metrics
Te6edf3assertNotNullTb4b4b4(Te6edf3metricsTb4b4b4)
Te6edf3assertEqualsTb4b4b4(T79c0ff1T79c0ff1fTb4b4b4, Te6edf3metricsTb4b4b4.Te6edf3oneWireTemperatureTb4b4b4(T79c0ff0Tb4b4b4)Tff7b72!!Tb4b4b4, T79c0ff0.01fTb4b4b4)
T8b949e// A stored 0°C is a real reading, so it must survive the lift rather than reading as absent.
Te6edf3assertEqualsTb4b4b4(T79c0ff0fTb4b4b4, Te6edf3metricsTb4b4b4.Te6edf3oneWireTemperatureTb4b4b4(T79c0ff1Tb4b4b4)Tff7b72!!Tb4b4b4, T79c0ff0.01fTb4b4b4)
Te6edf3assertEqualsTb4b4b4(T79c0ff3T79c0ff3fTb4b4b4, Te6edf3metricsTb4b4b4.Te6edf3oneWireTemperatureTb4b4b4(T79c0ff2Tb4b4b4)Tff7b72!!Tb4b4b4, T79c0ff0.01fTb4b4b4)
T8b949e// Channels the legacy list never carried normalize to the NaN the charts filter on.
Te6edf3assertTrueTb4b4b4(Te6edf3metricsTb4b4b4.Te6edf3oneWireTemperatureTb4b4b4(T79c0ff3Tb4b4b4)Tff7b72!!Tb4b4b4.Te6edf3isNaNTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`parseTelemetryLog normalizes absent per-channel readings to NaN`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTestTb4b4b4(Te6edf3testDispatcherTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3telemetry Tff7b72= Te6edf3TelemetryTb4b4b4(Te6edf3environment_metrics Tff7b72= Te6edf3EnvironmentMetricsTb4b4b4(Te6edf3temperature Tff7b72= T79c0ff2T79c0ff1fTb4b4b4)Tb4b4b4)
Te6edf3repositoryTb4b4b4.Te6edf3insertTb4b4b4(Te6edf3telemetryLogTb4b4b4(Ta5d6ff"Ta5d6ffabsent-channelsTa5d6ff"Tb4b4b4, T79c0ff0Tb4b4b4, Te6edf3telemetryTb4b4b4, Te6edf3nowMillisTb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3metrics Tff7b72= Te6edf3repositoryTb4b4b4.Te6edf3getTelemetryFromTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3singleTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3environment_metrics
Te6edf3assertNotNullTb4b4b4(Te6edf3metricsTb4b4b4)
Tff7b72for Tb4b4b4(Te6edf3channel Tff7b72in T79c0ff0 Te6edf3until Te6edf3TELEMETRY_CHANNEL_COUNTTb4b4b4) Tb4b4b4{
Te6edf3assertTrueTb4b4b4(Te6edf3metricsTb4b4b4.Te6edf3oneWireTemperatureTb4b4b4(Te6edf3channelTb4b4b4)Tff7b72!!Tb4b4b4.Te6edf3isNaNTb4b4b4(Tb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ff1-Wire chTffd700$Te6edf3channelTa5d6ff should be NaNTa5d6ff"Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3metricsTb4b4b4.Te6edf3adcVoltageTb4b4b4(Te6edf3channelTb4b4b4)Tff7b72!!Tb4b4b4.Te6edf3isNaNTb4b4b4(Tb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffADC chTffd700$Te6edf3channelTa5d6ff should be NaNTa5d6ff"Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`parseTelemetryLog preserves zero per-channel readings`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTestTb4b4b4(Te6edf3testDispatcherTb4b4b4) Tb4b4b4{
T8b949e// 0 V on an unloaded ADC input and 0°C on a probe are measurements, not "no sensor" sentinels.
Tff7b72val Te6edf3telemetry Tff7b72=
Te6edf3TelemetryTb4b4b4(Te6edf3environment_metrics Tff7b72= Te6edf3EnvironmentMetricsTb4b4b4(Te6edf3one_wire_temperature_ch0 Tff7b72= T79c0ff0fTb4b4b4, Te6edf3adc_voltage_ch0 Tff7b72= T79c0ff0fTb4b4b4)Tb4b4b4)
Te6edf3repositoryTb4b4b4.Te6edf3insertTb4b4b4(Te6edf3telemetryLogTb4b4b4(Ta5d6ff"Ta5d6ffzero-channelsTa5d6ff"Tb4b4b4, T79c0ff0Tb4b4b4, Te6edf3telemetryTb4b4b4, Te6edf3nowMillisTb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3metrics Tff7b72= Te6edf3repositoryTb4b4b4.Te6edf3getTelemetryFromTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3singleTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3environment_metrics
Te6edf3assertNotNullTb4b4b4(Te6edf3metricsTb4b4b4)
Te6edf3assertEqualsTb4b4b4(T79c0ff0fTb4b4b4, Te6edf3metricsTb4b4b4.Te6edf3oneWireTemperatureTb4b4b4(T79c0ff0Tb4b4b4)Tff7b72!!Tb4b4b4, T79c0ff0.01fTb4b4b4)
Te6edf3assertEqualsTb4b4b4(T79c0ff0fTb4b4b4, Te6edf3metricsTb4b4b4.Te6edf3adcVoltageTb4b4b4(T79c0ff0Tb4b4b4)Tff7b72!!Tb4b4b4, T79c0ff0.01fTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8fftelemetryLogTb4b4b4(
Te6edf3uuidTb4b4b4: Tffa657StringTb4b4b4,
Te6edf3nodeNumTb4b4b4: Tffa657IntTb4b4b4,
Te6edf3telemetryTb4b4b4: Te6edf3TelemetryTb4b4b4,
Te6edf3receivedDateTb4b4b4: Tffa657LongTb4b4b4,
Te6edf3wantResponseTb4b4b4: Tffa657Boolean Tff7b72= Tff7b72falseTb4b4b4,
Tb4b4b4) Tff7b72= Te6edf3MeshLogTb4b4b4(
Te6edf3uuid Tff7b72= Te6edf3uuidTb4b4b4,
Te6edf3message_type Tff7b72= Ta5d6ff"Ta5d6fftelemetryTa5d6ff"Tb4b4b4,
Te6edf3received_date Tff7b72= Te6edf3receivedDateTb4b4b4,
Te6edf3raw_message Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4,
Te6edf3fromNum Tff7b72= Te6edf3nodeNumTb4b4b4,
Te6edf3portNum Tff7b72= Te6edf3PortNumTb4b4b4.Te6edf3TELEMETRY_APPTb4b4b4.Te6edf3valueTb4b4b4,
Te6edf3fromRadio Tff7b72=
Te6edf3FromRadioTb4b4b4(
Te6edf3packet Tff7b72=
Te6edf3MeshPacketTb4b4b4(
Te6edf3from Tff7b72= Te6edf3nodeNumTb4b4b4,
Te6edf3decoded Tff7b72=
Te6edf3DataTb4b4b4(
Te6edf3payload Tff7b72= Te6edf3telemetryTb4b4b4.Te6edf3encodeTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toByteStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3portnum Tff7b72= Te6edf3PortNumTb4b4b4.Te6edf3TELEMETRY_APPTb4b4b4,
Te6edf3want_response Tff7b72= Te6edf3wantResponseTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Served by rngit 1.4.2 - Generated in 0.19s